// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_ASYNC_MODULE_BASE_HPP_
#define _XBASE_ASYNC_MODULE_BASE_HPP_

#include <boost/noncopyable.hpp>
#include <boost/static_assert.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/pool/detail/singleton.hpp>

#include "atomic.h"
#include "uuid.hpp"

#include "io_service_pool.hpp"
#include "async_module_stats.hpp"

namespace xbase
{

	// 
	// 异步模块的内存分配与管理
	// 

	template<typename T>
	inline
	void delete_async_module(T *p) {
		::delete p;
	}

#define _MACRO_VAR_ARGS_SUPPORT_
#ifdef _MACRO_VAR_ARGS_SUPPORT_

#	define new_async_module(T, args...) ::new T(args)

#elif
#	define new_async_module(T, args...) new_async_module_helper<T>(args)

	template<typename T>
	inline
	T *new_async_module_helper() {
		return ::new T();
	}

	template<typename T,
		 typename Arg>
	inline
	T *new_async_module_helper(Arg &arg) {
		return ::new T(arg);
	}

	template<typename T,
		 typename Arg1,
		 typename Arg2>
	inline
	T *new_async_module_helper(Arg1 &arg1, Arg2 &arg2) {
		return ::new T(arg1, arg2);
	}

	template<typename T,
		 typename Arg1,
		 typename Arg2,
		 typename Arg3>
	inline
	T *new_async_module_helper(Arg1 &arg1, Arg2 &arg2, Arg3 &arg3) {
		return ::new T(arg1, arg2, arg3);
	}

	template<typename T,
		 typename Arg1,
		 typename Arg2,
		 typename Arg3,
		 typename Arg4>
	inline
	T *new_async_module_helper(Arg1 &arg1, Arg2 &arg2, Arg3 &arg3, Arg4 &arg4) {
		return ::new T(arg1, arg2, arg3, arg4);
	}

	template<typename T,
		 typename Arg1,
		 typename Arg2,
		 typename Arg3,
		 typename Arg4,
		 typename Arg5>
	inline
	T *new_async_module_helper(Arg1 &arg1, Arg2 &arg2, Arg3 &arg3, Arg4 &arg4, Arg5 &arg5) {
		return ::new T(arg1, arg2, arg3, arg4, arg5);
	}

#endif	// _MACRO_VAR_ARGS_SUPPORT_

	class async_module
		: private boost::noncopyable
	{
	public:
		typedef boost::intrusive_ptr<async_module> ptr_type;
		
		typedef boost::details::pool::singleton_default< uuid<async_module> > uuid_type;
		
	public:
		async_module(const char *name)
			: m_name(name)
			, m_uuid(uuid_type::instance().get()) {
			atomic_set(&m_reference_counter, 0);
			async_module_stats::construction(this);
		}
		
		virtual
		~async_module() {
			async_module_stats::destruction(this);
		}

		const char *name() const {
			return m_name;
		}

		std::size_t id() const {
			return m_uuid;
		}

		// std::size_t use_count() const {
		// 	return atomic_read(&m_reference_counter);
		// }

		// void inc_use_count() const {
		// 	atomic_inc(&m_reference_counter);
		// }

	private:
		const char * const m_name;
		const std::size_t m_uuid;
		
		atomic_t m_reference_counter;

		friend inline
		void intrusive_ptr_add_ref(async_module *module) {
			atomic_inc(&module->m_reference_counter);
		}

		friend inline
		void intrusive_ptr_release(async_module *module) {
			if(atomic_dec_and_test(&module->m_reference_counter))
				delete_async_module(module);
		}
	};

	template<typename UpperLevel,
		 typename LowerLevel>
	class async_module_base
		: public async_module
	{
	public:
		typedef async_module_base<UpperLevel, LowerLevel> this_type;
		typedef boost::intrusive_ptr<this_type> ptr_type;

		typedef UpperLevel upper_level;
		typedef LowerLevel lower_level;

		typedef boost::asio::io_service io_service;

		BOOST_STATIC_ASSERT(upper_level::value >= lower_level::value);
	
	public:
		async_module_base(io_service_pool &pool,
				  const char *name = "async_module_base")
			: async_module(name)
			, m_upper_level_service(pool.get_io_service<upper_level>())
			, m_lower_level_service(pool.get_io_service<lower_level>()) {
		}

		io_service &get_upper_level_service() {
			return m_upper_level_service;
		}

		io_service &get_lower_level_service() {
			return m_lower_level_service;
		}

	private:
		io_service &m_upper_level_service;
		io_service &m_lower_level_service;
	};
	
} // namespace xbase

#endif	// _XBASE_ASYNC_MODULE_BASE_HPP_
